package com.atwisdom.star.core.bsl.modelClass.twins.Impl;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.atwisdom.star.common.actionType.modelClass.twins.TwinsActionType;
import com.atwisdom.star.common.util.JsonUtil;
import com.atwisdom.star.common.vo.*;
import com.atwisdom.star.core.bsl.modelClass.twins.TwinsInstanceBslService;
import com.atwisdom.star.core.dao.pojo.modelClass.twins.TwinsInstance;
import com.atwisdom.star.core.dsl.modelClass.consume.Impl.ConsumeInstanceDslServiceImpl;
import com.atwisdom.star.core.dsl.modelClass.logic.Impl.LogicInstanceDslServiceImpl;
import com.atwisdom.star.core.dsl.modelClass.resource.Impl.ResourceInstanceDslServiceImpl;
import com.atwisdom.star.core.dsl.modelClass.twins.Impl.TwinsInstanceDslServiceImpl;
import com.atwisdom.star.core.dsl.modelClass.twins.Impl.TwinsModelDslServiceImpl;
import com.atwisdom.star.core.dsl.modelClass.utils.QueryBuilder;
import com.atwisdom.star.exception.pojo.BusinessException;
import org.apache.commons.lang.StringUtils;
import org.springframework.aop.framework.AopContext;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.List;

@Service
public class TwinsInstanceBslServiceImpl implements TwinsInstanceBslService {
    private TwinsModelDslServiceImpl twinsModelDslService;
    private TwinsInstanceDslServiceImpl twinsInstanceDslService;
    private LogicInstanceDslServiceImpl logicInstanceDslService;
    private ConsumeInstanceDslServiceImpl consumeInstanceDslService;
    private ResourceInstanceDslServiceImpl resourceInstanceDslService;
    private QueryBuilder queryBuilder;
    @Autowired
    public void setQueryBuilder(QueryBuilder queryBuilder) {
        this.queryBuilder = queryBuilder;
    }
    @Autowired
    public void setResourceInstanceDslService(ResourceInstanceDslServiceImpl resourceInstanceDslService) {
        this.resourceInstanceDslService = resourceInstanceDslService;
    }

    @Autowired
    public void setConsumeInstanceDslService(ConsumeInstanceDslServiceImpl consumeInstanceDslService) {
        this.consumeInstanceDslService = consumeInstanceDslService;
    }
    @Autowired
    public void setLogicInstanceDslService(LogicInstanceDslServiceImpl logicInstanceDslService) {
        this.logicInstanceDslService = logicInstanceDslService;
    }

    @Autowired
    public void setTwinsModelDslService(TwinsModelDslServiceImpl twinsModelDslService) {
        this.twinsModelDslService = twinsModelDslService;
    }


    @Autowired
    public void setTwinsInstanceDslService(TwinsInstanceDslServiceImpl twinsInstanceDslService) {
        this.twinsInstanceDslService = twinsInstanceDslService;
    }

    /**
     * 服务工厂方法
     * @param actionDataList 参数
     * @return 参数
     * @throws BusinessException 异常
     */
    @Transactional
    public ResultInfo<?> responseFactory(List<ActionData<JSONObject>> actionDataList) throws BusinessException {
        ResultInfo<?> resultInfo = null;
        for (ActionData<JSONObject> actionData : actionDataList) {
            String action = actionData.getAction();
            TwinsActionType actionType = TwinsActionType.valueOf(action);
            String methodName = actionType.getMethodName();
            resultInfo = this.execMethod(methodName, actionData);
        }
        return resultInfo;
    }

    /**
     * 反射执行业务单元方法
     *
     * @param methodName 方法名
     * @param actionData 方法参数
     * @return 返回结果
     * @throws BusinessException 业务异常
     */
    public ResultInfo<?> execMethod(String methodName, ActionData<JSONObject> actionData) throws BusinessException {
        Class<? extends TwinsInstanceBslServiceImpl> clz = this.getClass();
        try {
            Method method = clz.getMethod(methodName, ActionData.class);
            TwinsInstanceBslServiceImpl service = (TwinsInstanceBslServiceImpl) AopContext.currentProxy();
            return (ResultInfo<?>) method.invoke(service, actionData);
        } catch (NoSuchMethodException ex) {
            throw new BusinessException("999999", "没有找到该方法(" + methodName + ")", ex);
        } catch (IllegalAccessException ex) {
            throw new BusinessException("999999", "没有访问该方法权限(" + methodName + ")", ex);
        } catch (InvocationTargetException ex) {
            Throwable targetException = ex.getTargetException();
            if (targetException instanceof BusinessException) {
                BusinessException bex = (BusinessException) targetException;
                throw new BusinessException("999999", bex.getErrorMsg(), ex);
            } else {
                throw new BusinessException("999999", "出错了请重试：(" + methodName + ")---" + ex.getMessage(), ex);
            }
        }
    }
    /**
     * 查询全部摘要（通用）
     *
     * @param actionData 参数
     * @return 返回值
     */
    @Override
    public ResultInfo<?> queryAllInfo(ActionData<JSONObject> actionData) {
        List<JSONObject> jsonObjectList = this.twinsInstanceDslService.queryAllInfo();
        return JsonResult.success(jsonObjectList);
    }

    /**
     * 分页查询全部摘要（通用）
     *
     * @param actionData 参数
     * @return 返回值
     */
    @Override
    public ResultInfo<PageInfo> queryAllInfoByPage(ActionData<JSONObject> actionData) {
        int pageNumber = actionData.getPageNumber();
        int pageSize = actionData.getPageSize();
        String orderBy = actionData.getOrderBy();
        PageInfo pageInfo = this.twinsInstanceDslService.queryAllInfoByPage(pageNumber, pageSize, orderBy);
        return JsonResult.success(pageInfo);
    }

    /**
     * 查询全部数据（通用）
     *
     * @param actionData 参数
     * @return 返回值
     */
    @Override
    public ResultInfo<?> queryAll(ActionData<JSONObject> actionData) {
        List<JSONObject> jsonObjectList = this.twinsInstanceDslService.queryAll();
        return JsonResult.success(jsonObjectList);
    }

    /**
     * 分页查询全部数据（通用）
     *
     * @param actionData 参数
     * @return 返回值
     */
    @Override
    public ResultInfo<?> listAllByPage(ActionData<JSONObject> actionData) {
        int pageNumber = actionData.getPageNumber();
        int pageSize = actionData.getPageSize();
        String orderBy = actionData.getOrderBy();
        PageInfo pageInfo = this.twinsInstanceDslService.listAllByPage(pageNumber, pageSize, orderBy);
        return JsonResult.success(pageInfo);
    }

    /**
     * 按条件查询模型
     *
     * @param actionData 参数
     * @return 返回值
     */
    @Override
    public ResultInfo<?> query(ActionData<JSONObject> actionData) {
        String condition = actionData.getCondition();
        String className = actionData.getClassName();
        String orderBy = actionData.getOrderBy();
        String hierValueCondition = actionData.getHierValueCondition();
        boolean needRootFlag = actionData.isNeedRootFlag();
        List<JSONObject> queryJsonList = this.twinsInstanceDslService.query(condition, className, orderBy, hierValueCondition, needRootFlag);
        return JsonResult.success(queryJsonList);
    }

    /**
     * 查询实例容器hier
     * @param actionData 参数
     * @return 返回hier
     */
    public ResultInfo<?> queryHierById(ActionData<JSONObject> actionData) {
        Long id = actionData.getId();
        JSONObject jsonObject = this.twinsInstanceDslService.queryHierById(id);
        return JsonResult.success(jsonObject);
    }



    /**
     * 按条件分页查询模型实例摘要
     * @param actionData 参数
     * @return 返回结果
     */
    public ResultInfo<?> queryInfoByPage(ActionData<JSONObject> actionData) {
        int pageNumber = actionData.getPageNumber();
        int pageSize = actionData.getPageSize();
        String condition = actionData.getCondition();
        String className = actionData.getClassName();
        String orderBy = actionData.getOrderBy();
        PageInfo pageInfo = this.twinsInstanceDslService.queryInfoByPage(pageNumber, pageSize, condition, className, orderBy);
        return JsonResult.success(pageInfo);
    }

    /**
     * 按条件分页查询模型实例
     * @param actionData 参数
     * @return 返回结果
     */
    public ResultInfo<?> queryByPage(ActionData<JSONObject> actionData) {
        int pageNumber = actionData.getPageNumber();
        int pageSize = actionData.getPageSize();
        String condition = actionData.getCondition();
        String className = actionData.getClassName();
        String orderBy = actionData.getOrderBy();
        String hierValueCondition = actionData.getHierValueCondition();
        PageInfo pageInfo = this.twinsInstanceDslService.queryByPage(pageNumber, pageSize, condition, className, orderBy, hierValueCondition);
        return JsonResult.success(pageInfo);
    }

    /**
     * 更新模型属性字段
     * 更新，需要同步更新实例，同步更新历史数据
     * 1、className 和 自定字段
     *
     * @param actionData 参数
     * @return 返回值
     */
    @Override
    public ResultInfo<?> updateById(ActionData<JSONObject> actionData) {
        List<JSONObject> data = actionData.getData();
        JSONObject updateJson = JsonUtil.toJSONObject(data.get(0));
        boolean updateNullFlag = actionData.isUpdateNullFlag();
        if(updateNullFlag){
            this.twinsInstanceDslService.updateFieldNullById(updateJson);
        }
        JSONObject jsonObject = this.twinsInstanceDslService.updateById(updateJson);
        return JsonResult.success(jsonObject);
    }

    /**
     * 更新实例hier
     * @param actionData 更新参数
     * @return 返回更新的实例
     */
    public ResultInfo<?>  updateHier(ActionData<JSONObject> actionData){
        List<JSONObject> data = actionData.getData();
        JSONObject jsonObject = data.get(0);
        String className = jsonObject.getString("className");
        JSONObject hier = jsonObject.getJSONObject("hier");
        JSONObject hierProperties = this.twinsModelDslService.queryHierProperties(className);

        JSONObject hierJson = queryBuilder.fetchHierBy(hierProperties, hier);
        dealHierLinkInstance(hierJson);
        TwinsInstance twinsInstance = this.twinsInstanceDslService.findByClassName(className);
        twinsInstance.setHier(hierJson);
        JSONObject infoJsonObject = twinsInstance.getInfoJsonObject();
        JSONObject resultJsonObject = twinsInstanceDslService.updateById(infoJsonObject);
        return JsonResult.success(resultJsonObject);
    }

    /**
     * 处理hierLink
     * @param hier 参数
     */
    private void dealHierLinkInstance(JSONObject hier){
        JSONArray tempContent = hier.getJSONArray("content");
        JSONArray content = new JSONArray();
        for (int i = 0; i < tempContent.size(); i++) {
            JSONObject contentJson = tempContent.getJSONObject(i);
            JSONObject link = contentJson.getJSONObject("link");
            this.createInstance(link);
            contentJson.put("link",link);
            content.add(contentJson);
        }
        hier.put("content",content);
    }

    /**
     * 根据link 创建实例
     * @param link 创建实例参数
     */
    private void createInstance(JSONObject link){
        if (link == null) {
            return;
        }

        String id = link.getString("id");
        if (StringUtils.isNotBlank(id)) {
            return;
        }

        JSONObject values = link.getJSONObject("values");
        if(values==null || values.size() < 1){
            return;
        }
        String type = link.getString("type");
        String className = link.getString("className");
        if (StringUtils.isBlank(type) || StringUtils.isBlank(className)) {
            return;
        }

        ModelType modelType = ModelType.getByCode(type);
        JSONObject jsonObject;
        Long linkId;
        switch (modelType){
            case Consume:
                jsonObject = consumeInstanceDslService.add(type, className, className,values);
                linkId = jsonObject.getLong("id");
                link.put("id",linkId);
                break;
            case Resource:
                jsonObject = resourceInstanceDslService.add(type, className, className,values);
                linkId = jsonObject.getLong("id");
                link.put("id",linkId);
                break;
            case Logic:
                jsonObject= logicInstanceDslService.add(type, className, className,values);
                linkId = jsonObject.getLong("id");
                link.put("id",linkId);
                break;
            default:
                break;
        }
    }

    /**
     * 更新模型属性字段
     * 更新，需要同步更新实例，同步更新历史数据
     * 1、className 和 自定字段
     *
     * @param actionData 参数
     * @return 返回值
     */
    @Override
    public ResultInfo<?> updateByIds(ActionData<JSONObject> actionData) {
        List<JSONObject> jsonObjectList = this.twinsInstanceDslService.updateByIds(actionData.getData());
        return JsonResult.success(jsonObjectList);
    }

    /**
     * 更新模型类型和类名（配置阶段）
     *
     * @param actionData 参数
     * @return 返回值
     */
    @Override
    public ResultInfo<?> updateClassName(ActionData<JSONObject> actionData) {
        List<JSONObject> data = actionData.getData();
        List<JSONObject> jsonObjectList = this.twinsInstanceDslService.updateClassName(data.get(0));
        return JsonResult.success(jsonObjectList);
    }
}
